import React, { useState, useCallback, memo, useMemo } from 'react'

type ChildProps = {
  click: () => void
}

type Child2Props = {
  user: { age: number }
}

const Child1 = memo(({ click }: ChildProps) => {
  console.log('Child1 组件更新')
  return (
    <div style={{ backgroundColor: 'lightsalmon', padding: 5 }}>
      子组件1：<button onClick={click}>点击</button>
    </div>
  )
})

const Child2 = React.memo(({ user }: Child2Props) => {
  console.log('Child2 组件更新')
  return (
    <div style={{ backgroundColor: 'lightgoldenrodyellow', padding: 5 }}>子组件2 -- {user.age}</div>
  )
})

const App = () => {
  const [count, setCount] = useState(0)
  const [theme, setTheme] = useState('lightseagreen')

  const handleClick = useCallback(() => {
    console.log('依赖 count 数据')
    setCount(count + 10)
  }, [count])

  // useMemo 可以在组件更新期间保持任意数据引用相等，一般用来处理对象类型的数据
  // 对比：useCallback 只能记忆函数，而 useMemo 可以记忆任意数据
  // 作用：记忆任意数据，这个被记住的数据会一直生效，直到依赖项发生改变

  // 第一个参数：回调函数，必选选项，该回调函数会被立即调用，并通过返回值指定需要被记住的数据
  // 第二个参数：依赖数据，必选选项，用于指定回调函数中依赖的数据，没有依赖时，必须传入空数组
  // 返回值：useMemo 记忆的数据
  // useMemo 记忆的数据会一直生效，一直返回同一个数据，知道依赖项发生改变

  // 没有依赖项的情况
  // const user = useMemo(() => {
  //   return { age: 10 }
  // }, [])

  const user = useMemo(() => {
    console.log('useMemo 回调会被立即执行')
    return { age: 1 + count }
  }, [count])

  return (
    <div style={{ backgroundColor: theme, padding: 10 }}>
      <button
        onClick={() => setTheme(theme === 'lightseagreen' ? 'lightskyblue' : 'lightseagreen')}
      >
        切换主题
      </button>

      <h1>计数器：{count}</h1>
      <button onClick={() => setCount(count + 1)}>+1</button>

      <hr />

      {/* 子组件 */}
      <Child1 click={handleClick} />

      <hr />

      <Child2 user={user} />
    </div>
  )
}

export default App
